(* MODULE IMAGE *)

(* Dimensions d'une image *)
let get_dims img =
  ((Sdlvideo.surface_info img).Sdlvideo.w,
   (Sdlvideo.surface_info img).Sdlvideo.h)


(* Initialisation de SDL *)
let sdl_init () =
  begin
    Sdl.init [`EVERYTHING];
    Sdlevent.enable_events Sdlevent.all_events_mask;
  end


(* Fonctions qui comparent des couleurs - Fonction interne aux fonctions
   principales *)
let compare_colors (x,y,z) (a,b,c)=
  let c1 = x + y + z in
  let c2 = a + b + c in
  if c1 < c2 then
    1
  else if c1 > c2 then
    -1
  else
    0

let compare_pixels image (i1,j1) (i2,j2) =
  compare_colors (Sdlvideo.get_pixel_color image i1 j1)
    (Sdlvideo.get_pixel_color image i2 j2)

(* Insert l'element x dans la liste l *)
let rec insert compare f x = function
  | [] -> [x]
  | e::l -> if compare (f x) (f e) then x::e::l else if f x = f e then
      e::l
    else
      e::insert compare f x l

(* Fonction utilisee pour comparer deux couleurs en niveau de gris *)
let compare_grey (a,b,c) (x,y,z) = a < x

let level (r,g,b) =
  ((float)r *. 0.3 +. (float)g *. 0.59 +. (float)b *. 0.11) /. 255.

let color2grey (r,g,b) =
  let g = int_of_float ((level (r,g,b)) *. 255.) in
    (g,g,g)

(*Retourne l'image filtree avec le filtre median, plus le scale est grand, plus
* le filtre sera violent *)

              
let median_filter image scale result =
  let (w,h) = get_dims image in
  let l = ref [] in
    for i=0 to w - 1 do
      for j = 0 to h - 1 do
        if i >= scale && i <= w - scale && j >= scale && j <= h - scale then
          begin
            for i1= i - scale to i + scale do
              for j1 = j - scale to j + scale do
                l := (Sdlvideo.get_pixel_color image i1 j1)::!l
              done
            done;
            Sdlvideo.put_pixel_color result i j 
              (List.nth (List.sort compare_colors !l) 
                 ((List.length !l) / 2));
            l := []
          end
        else
          Sdlvideo.put_pixel_color result i j (Sdlvideo.get_pixel_color image i j)
      done
    done
      


        (* Detoure les zones de couleur, renvoie l'image ainsi que la liste
   des couleurs triees par niveau de gris *)
let cut image result =
  let (width,height) = get_dims image in
  let color_list = ref [] in
    for i=0 to width - 1 do
      for j=0 to height - 1 do
	if(compare_pixels image (i,j) (i+1, j) = 1 ||
            compare_pixels image (i,j) (i-1, j) = 1 ||
            compare_pixels image (i,j) (i, j+1) = 1 ||
            compare_pixels image (i,j) (i, j-1) = 1)
	then
          Sdlvideo.put_pixel_color result i j (0,0,0)
	else
          Sdlvideo.put_pixel_color result i j
	    (Sdlvideo.get_pixel_color
      image i j);
	color_list := insert compare_grey color2grey
	  (Sdlvideo.get_pixel_color image i j) !color_list
      done
    done;
    !color_list


(* Fonction de quadrillage de l'image *)
let sample image space result =
  let (width,height) = get_dims image in
    for i=0 to width - 1 do
      for j=0 to height - 1 do
	if(i mod space = 0 || j mod space = 0 || i mod space = j mod space) then
	  Sdlvideo.put_pixel_color result i j (0,0,0)
	else
          Sdlvideo.put_pixel_color result i j (Sdlvideo.get_pixel_color
						 image i j);
      done;
    done


            
(* Fonction qui traite l'image, la sauvegarde temporairement et
   renvoie son chemin - Juste pour tester *)
let process_image image_name color_list =
  let image = ref (Sdlloader.load_image image_name) in
    if (Sys.file_exists (image_name^(".temp"))) then
      image := Sdlloader.load_image (image_name^(".temp"))
    else
      image := Sdlloader.load_image image_name;
    let (w,h) = get_dims !image in
    let result = Sdlvideo.create_RGB_surface_format !image [] w h in
      color_list := cut !image result;
      Sdlvideo.save_BMP result (image_name^(".temp2"));
      (image_name^(".temp2"))

let sample_image image_name space =
  let image = Sdlloader.load_image (image_name^(".temp2")) in
  let (w,h) = get_dims image in
  let result = Sdlvideo.create_RGB_surface_format image [] w h in
    sample image space result;
    Sdlvideo.save_BMP result (image_name^(".temp3"));
    (image_name^(".temp3"))

let filter_image image_name scale =
  if (Sys.file_exists
        ((image_name)^".temp"))
  then
    begin
      let image = Sdlloader.load_image ((image_name)^".temp") in
      let (w,h) = get_dims image in
      let result = Sdlvideo.create_RGB_surface_format image [] w h in
      median_filter image scale result;
      Sdlvideo.save_BMP result (image_name^(".temp"));
      (image_name^(".temp"))
    end  
  else
    begin
      let image = Sdlloader.load_image image_name in
      let (w,h) = get_dims image in
      let result = Sdlvideo.create_RGB_surface_format image [] w h in
      median_filter image scale result;
      Sdlvideo.save_BMP result (image_name^(".temp"));
      (image_name^(".temp"))
    end
